/**
 * 
 */
package will.icecoffe.core;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.annotation.Resources;

import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import will.icecoffe.utils.Page;

/**
 * @author will
 * 
 */
@Component("DAS")
public class SimpleDataAccessService<T> {

	private Class<T> type;

	@Resource(name = "basicSaver")
	private Saver saver;

	@Resource(name = "basicUpdater")
	private Updater updater;

	@Resource(name = "basicDeleter")
	private Deleter deleter;

	@Resource(name = "basicHQLFinder")
	private Finder hqlfinder;

	@Resource(name = "basicSQLFinder")
	private Finder sqlfinder;
	
	@Resource(name = "basicQBCFinder")
	private Finder qbcfinder;

	private Map<String, Finder> finders;

	public SimpleDataAccessService() {

	}

	public SimpleDataAccessService(Class<T> type) {
		this.type = type;
	}

	public Saver getSaver() {
		return saver;
	}

	public void setSaver(Saver saver) {
		this.saver = saver;
	}

	public Finder getHqlfinder() {
		return hqlfinder;
	}

	public void setHqlfinder(Finder hqlfinder) {
		this.hqlfinder = hqlfinder;
	}

	public Finder getSqlfinder() {
		return sqlfinder;
	}

	public void setSqlfinder(Finder sqlfinder) {
		this.sqlfinder = sqlfinder;
	}

	public Updater getUpdater() {
		return updater;
	}

	public void setUpdater(Updater updater) {
		this.updater = updater;
	}

	public Deleter getDeleter() {
		return deleter;
	}

	public void setDeleter(Deleter deleter) {
		this.deleter = deleter;
	}

	public Map<String, Finder> getFinders() {
		return finders;
	}

	public void setFinders(Map<String, Finder> finders) {
		this.finders = finders;
	}

	/**
	 * 将指定对象持久化。在未指定保存策略情况下，默认使用BasicSaver保存策略。
	 * 
	 * @param obj
	 *            待保存的对象
	 * @return 返回持久化后的对象
	 * @throws DataAccessException
	 */
	@Transactional(rollbackFor=DataAccessException.class)
	public T save(T obj) throws DataAccessException {

		if (null == this.saver)
			this.saver = new BasicSaver<T>();
		
		return (T) saver.save(obj);

	}

	/**
	 * 更新指定对象。以主键值进行判断。在未指定更新策略情况下，默认使用BasicUpdater策略。
	 * 
	 * @param obj
	 *            待更新的对象
	 * @throws DataAccessException
	 */
	public void update(Object obj) throws DataAccessException {

		if (null == this.updater)
			this.updater = new BasicUpdater();

		updater.update(obj);

	}

	public void saveOrUpdate(Object obj) throws DataAccessException {

	}

	/**
	 * 删除指定对象，以主键值为准。在未指定删除策略情况下，默认使用BasicDeleter策略。
	 * 
	 * @param obj
	 *            待删除的对象
	 * @throws DataAccessException
	 */
	public void delete(Object obj) throws DataAccessException {

		if (null == this.deleter)
			this.deleter = new BasicDeleter();

		deleter.delete(obj);

	}

	/**
	 * <p>
	 * 使用指定策略进行查询。默认情况下系统会提供一个BasicHQLFinder和一个BasicSQLFinder。
	 * 当用户未提供任何查询策略时，系统会使用默认注入的BasicHQLFinder、BasicSQLFinder。其调用方式为：
	 * </p>
	 * 		<p>find(sql/hql, QueryName, [QueryParameters])</p>
	 * <p>
	 * 例如：<br/>
	 * 		find("hql", "FindUserWithID", 0)<br/>
	 * 		find("hql", "FindAllUsers")<br/>
	 * 		find("sql", "FindUserWithIDNavi", 0)<br/>
	 * 		find("sql", "FindAllUserNavi")<br/>
	 * </p>
	 * <p>
	 * 当用户提供了自定义的查询策略后，系统将使用用户自定义的查询策略进行查询。其调用方式为：
	 * </p>
	 * <p>
	 * 		find(FinderName, [QueryParameters])
	 * </p>
	 * <p>
	 * 例如：<br/>
	 * 		find("MyFinder", new Date(), 1);
	 * </p>
	 * <p>
	 * 注意：<br/>
	 * 1、用户自定义的查询策略不能以“sql”或者“hql”命名。“sql”，“hql”是系统保留命名，会覆盖用户的默认设置。
	 * 2、用户自定义查询策略后默认的BasicHQLFinder、BasicSQLFinder仍将有效，使用方法与未提供自定义查询策略时相同。
	 * </p>
	 * 
	 * <p>
	 * 查询策略集合在Spring ApplicationContext中定义注入。
	 * </p>
	 * 
	 * @param finder
	 *            查询策略集合
	 * @param args
	 *            查询策略所调用参数集合
	 * @return 返回查询结果
	 * @throws DataAccessException
	 */
	public List<T> find(String finder, Object... args)
			throws DataAccessException {

		if (null == this.finders || 0 == this.finders.size() || finder.equals("sql") || finder.equals("hql")) {
			if ("hql".equals(finder))
				return this.hqlfinder.find(args);
			else if ("sql".equals(finder))
				return this.sqlfinder.find(args);
			else if ("qbc".equals(finder))
				return this.qbcfinder.find(args);
			else
				throw new NullPointerException("There is NO Finders can be used!\n查询器不存在或注入失败！");
		}

		if (null == finders.get(finder)) {
			throw new NullPointerException("There is NO Finders named with \""
					+ finder + "\"!\n没有找到名为“" + finder + "”的查询器！");
		}
		
		return finders.get(finder).find(args);

	}
	
	public Page<T> find(String finder, int page, int rows, Object... args) throws DataAccessException {
		
		if (null == this.finders || 0 == this.finders.size() || finder.equals("sql") || finder.equals("hql")) {
			// throw new NullPointerException("There is NO Finders can be used!\n查询器不存在或注入失败！");
			if ("hql".equals(finder))
				return this.hqlfinder.find(page, rows, args);
			else if ("sql".equals(finder))
				return this.sqlfinder.find(page, rows, args);
			else if ("qbc".equals(finder))
				return this.qbcfinder.find(page, rows, args);
			else
				throw new NullPointerException("There is NO Finders can be used!\n查询器不存在或注入失败！");
		}

		if (null == finders.get(finder)) {
			throw new NullPointerException("There is NO Finders named with \""
					+ finder + "\"!\n没有找到名为“" + finder + "”的查询器！");
		}
		
		return finders.get(finder).find(page, rows, args);
		
	}

}
